package com.shuqing.download.engine.data.strategy;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.shuqing.download.engine.DownLoadHeader;
import com.shuqing.download.engine.DownLoadTaskDto;
import com.shuqing.download.engine.config.EngineConfig;
import com.shuqing.download.engine.constants.TaskStatusEnum;
import com.shuqing.download.engine.data.DataFillHandler;
import com.shuqing.download.model.DownLoadTask;
import com.shuqing.download.service.owner.DownLoadTaskService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author wangshuqing
 * @date 2023/2/12 16:27
 */
@Slf4j
@Component
public class RedisFillHandler implements DataFillHandler {

    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private EngineConfig engineConfig;
    @Autowired
    private DownLoadTaskService downLoadTaskService;

    @Override
    public void supplement() {
        log.info("开始填充");
        Boolean lock=redisTemplate.opsForValue()
                .setIfAbsent(
                        engineConfig.getRedisSupplementKey(),
                        this.getClass().getName(),
                        engineConfig.getRedisExpireTimeOut(),
                        TimeUnit.SECONDS);
        if(!lock){
            log.info("结束填充,锁未释放");
            return ;
        }
        String dataKey=engineConfig.getRedisSupplementData();
        Long size=redisTemplate.opsForList().size(dataKey);
        if(size==null || size.intValue()>engineConfig.getSupplementFillLimit()){
            log.info("结束填充,队列充足:{}",size);
            return ;
        }
        List<DownLoadTask> lsData=queryDataFormDb();
        if(CollectionUtil.isEmpty(lsData)){
            log.info("结束填充,没有数据可以填充");
            return ;
        }
        List<String> ls=dataToStringList(lsData);
        updateTaskStatus(lsData);
        redisTemplate.opsForList().leftPushAll(dataKey,ls);
        log.info("结束填充,填充数为:{}",ls.size());
    }



    @Override
    public DownLoadTaskDto nextData() {
        String json=redisTemplate.opsForList().rightPop(engineConfig.getRedisSupplementData());
        if(StrUtil.isNotBlank(json)){
            DownLoadTask task= JSON.parseObject(json,DownLoadTask.class);
            DownLoadTaskDto dto=new DownLoadTaskDto();
            dto.setId(task.getId());
            dto.setActuator(task.getActuator());
            dto.setFileName(task.getFileName());
            dto.setRetryCount(task.getRetryCount());
            dto.setSqlParams(task.getSqlParams());
            dto.setSqlStr(task.getSqlStr());
            if(StringUtils.isNotBlank(task.getHeaders())){
                dto.setExportHeaders(JSON.parseArray(task.getHeaders(),DownLoadHeader.class));
            }
            return dto;
        }
        return null;
    }

    /**
    * 对象转list<String>
    * @date 2023/2/12 18:08
    * @author wangshuqing
    * @param lsData
     *@return java.util.List<java.lang.String>
    * */
    private List<String> dataToStringList(List<DownLoadTask> lsData){
        return lsData.stream().map(e-> JSON.toJSONString(e)).collect(Collectors.toList());
    }

    /***
    * 从数据库获取休眠状态的数据：按时间倒叙
    * @date 2023/2/12 18:02
    * @author wangshuqing
    * @param
     *@return java.util.List<com.shuqing.download_center_demo.engine.DownLoadTaskDto>
    * */
    private List<DownLoadTask> queryDataFormDb(){
        QueryWrapper<DownLoadTask> queryWrapper=new QueryWrapper<>();
        queryWrapper
                .lambda()
                .eq(DownLoadTask::getTaskStatus, TaskStatusEnum.SLEEP)
                .orderByDesc(DownLoadTask::getCreateTime)
                .last("limit "+engineConfig.getMaxQueueCount());
        List<DownLoadTask> ls=downLoadTaskService.list(queryWrapper);
        return ls;
    }

    private void updateTaskStatus(List<DownLoadTask> lsData){
        if(CollectionUtil.isNotEmpty(lsData)){
            DownLoadTask update=new DownLoadTask();
            update.setTaskStatus(TaskStatusEnum.QUEUE.name());
            QueryWrapper<DownLoadTask> wrapper=new QueryWrapper();
            wrapper.lambda().in(DownLoadTask::getId,lsData.stream().map(e->e.getId()).collect(Collectors.toList()));
            downLoadTaskService.update(update,wrapper);
        }
    }

}
